package bs.app.android;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;

public class Graphics {
	public static final int TOP = 16;
	public static final int LEFT = 4;
	public static final int RIGHT = 8;
	public static final int BOTTOM = 32; 
	public static final int HCENTER = 1; 
	public static final int VCENTER = 2; 
	public static final int BASELINE = 64;
	
	public static final int SOLID = 0;
	public static final int DOTTED = 1;
	
	private Canvas _canvas = null;
	private Rect clip = null;;
	public Paint p = new Paint();
	
	private int dx = 0;
	private int dy = 0;
	
	@SuppressWarnings("unused")
	private Graphics(){}
	
	protected Graphics(Canvas canvas){
		_canvas = canvas;
		clip = new Rect(0,0,0,0);
		resetTranslate();
	}
	
	public void setClip(int x, int y, int width, int height){
		if (x == clip.left && x+ width == clip.right && y == clip.top && y + height == clip.bottom) {
			return;
		}
        clip.left = dx + x;
        clip.top = dy + y;
        clip.right = dx + x + width;
        clip.bottom = dy + y + height;
        _canvas.clipRect(clip, Op.REPLACE);
        //namnv begin 
//        _canvas.save(Canvas.ALL_SAVE_FLAG);
//        _canvas.clipRect(clip.left, clip.top, clip.right, clip.bottom);		
        //namnv end
	}
	
	public void setClip1(int left, int top, int right, int bottom) {
		_canvas.save(Canvas.ALL_SAVE_FLAG);
		_canvas.clipRect(left, top, left + right, top + bottom);		
	}
	
	public void restoreClip() {
		_canvas.restore();
	}
	
	public void drawLine(int x, int y, int x1, int y1) {
		p.setStyle(Paint.Style.STROKE);
		_canvas.drawLine(dx + x, dy + y, dx + x1, dy + y1, p);
	}
	
	public void setFont(Font font) {
		// nothing: drawString use Font.paint
	}
	public void drawString(String text, int x, int y, int flag) {
		int newx = x;
        int newy = y;
        
        if (flag == 0) {
        	flag = Graphics.TOP | Graphics.LEFT;
        }

        if ((flag & Graphics.RIGHT) == Graphics.RIGHT) {
            newx -= p.measureText(text);
        } else if ((flag & Graphics.HCENTER) == Graphics.HCENTER) {
            newx -= ((int)p.measureText(text) >> 1);
        }
        if ((flag & Graphics.TOP) == Graphics.TOP) {
            newy -= p.getFontMetricsInt().ascent;
        } else if ((flag & Graphics.BOTTOM) == Graphics.BOTTOM) {
            newy -= p.getFontMetricsInt().descent;
        } else if ((flag & Graphics.VCENTER) == Graphics.VCENTER) {
            newy -= ((int)p.getTextSize() >> 1);
        }
        Font.paint.setAntiAlias(true);
		_canvas.drawText(text, dx + newx, dy + newy, Font.paint);
	}
	public void drawStringStore(String text, int x, int y, int flag) {
		int newx = x;
        int newy = y;
        
        if (flag == 0) {
        	flag = Graphics.TOP | Graphics.LEFT;
        }

        if ((flag & Graphics.RIGHT) == Graphics.RIGHT) {
            newx -= p.measureText(text);
        } else if ((flag & Graphics.HCENTER) == Graphics.HCENTER) {
            newx -= ((int)p.measureText(text) >> 1);
        }
        if ((flag & Graphics.TOP) == Graphics.TOP) {
            newy -= p.getFontMetricsInt().ascent;
        } else if ((flag & Graphics.BOTTOM) == Graphics.BOTTOM) {
            newy -= p.getFontMetricsInt().descent;
        } else if ((flag & Graphics.VCENTER) == Graphics.VCENTER) {
            newy -= ((int)p.getTextSize() >> 1);
        }
        Font.paint.setStyle(Paint.Style.FILL);        
        Font.paint.setStrokeWidth(1);
        Font.paint.setAntiAlias(true);
		_canvas.drawText(text, dx + newx, dy + newy, Font.paint);
	}
	
	public void drawChar(char c, int x, int y, int flag) {
		drawString(c+"", dx + x, dy + y, flag);
	}
	
	public void drawRGB(int[] rgbData, int offset, int scanlength, int x,
			int y, int width, int height, boolean processAlpha) {
        // this is less than ideal in terms of memory
        // but it's the easiest way

        if (rgbData == null)
            throw new NullPointerException();

        if (width == 0 || height == 0) {
            return;
        }

        int l = rgbData.length;

        if (width < 0 || height < 0 || offset < 0 || offset >= l || (scanlength < 0 && scanlength * (height - 1) < 0)
                || (scanlength >= 0 && scanlength * (height - 1) + width - 1 >= l))
            throw new ArrayIndexOutOfBoundsException();

        int[] rgb = new int[width * height];
        // this way we dont create yet another array in createImage
        int transparencyMask = processAlpha ? 0 : 0xff000000;
        for (int row = 0; row < height; row++) {
            for (int px = 0; px < width; px++)
                rgb[row * width + px] = rgbData[offset + px] | transparencyMask;
            offset += scanlength;
        }

        // help gc
        rgbData = null;
        Image img = Image.createRGBImage(rgb, width, height, true);
        drawImage(img, dx + x, dy + y, TOP | LEFT);
	}
	
	public void drawImage(Image img, int x, int y, int flag){
		int newx = x;
        int newy = y;

        if (flag == 0) {
        	flag = Graphics.TOP | Graphics.LEFT;
        }

        if ((flag & Graphics.RIGHT) == Graphics.RIGHT) {
            newx -= img.getWidth();
        } else if ((flag & Graphics.HCENTER) == Graphics.HCENTER) {
            newx -= (img.getWidth() >> 1);
        }
        if ((flag & Graphics.BOTTOM) != 0) {
            newy -= img.getHeight();
        } else if ((flag & Graphics.VCENTER) == Graphics.VCENTER) {
            newy -= (img.getHeight()>>1);
        }

		_canvas.drawBitmap(img.bmp, dx + newx, dy + newy, null);
	}
	public void drawRegion(Image src, int x_src, int y_src, int width,
			int height, int transform, int x_dst, int y_dst, int flag){
		
		// may throw NullPointerException, this is ok
        if (x_src + width > src.getWidth() || y_src + height > src.getHeight() || width < 0 || height < 0 || x_src < 0
                || y_src < 0)
            throw new IllegalArgumentException("Area out of Image");

        // this cannot be done on the same image we are drawing
        // check this if the implementation of getGraphics change so
        // as to return different Graphic Objects on each call to
        // getGraphics
        if (src.getGraphics() == this)
            throw new IllegalArgumentException("Image is source and target");

        if (flag == 0) {
        	flag = Graphics.TOP | Graphics.LEFT;
        }

		int newx = x_dst;
        int newy = y_dst;
        if ((flag & Graphics.RIGHT) == Graphics.RIGHT) {
            newx -= width;
        } else if ((flag & Graphics.HCENTER) == Graphics.HCENTER) {
            newx -= (width >> 1);
        }
        if ((flag & Graphics.BOTTOM) != 0) {
            newy -= height;
        } else if ((flag & Graphics.VCENTER) == Graphics.VCENTER) {
            newy -= (height>>1);
        }
        
        if(transform != Sprite.TRANS_NONE){
        	_canvas.save();
        	
        	switch(transform){
        	case Sprite.TRANS_MIRROR:
        		_canvas.getMatrix().setScale(-1, 1);
        		break;
        	case Sprite.TRANS_MIRROR_ROT90:
        		_canvas.getMatrix().setScale(-1, 1);
        		_canvas.rotate(90, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
         	case Sprite.TRANS_MIRROR_ROT180:
        		_canvas.getMatrix().setScale(-1, 1);
        		_canvas.rotate(180, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
         	case Sprite.TRANS_MIRROR_ROT270:
        		_canvas.getMatrix().setScale(-1, 1);
        		_canvas.rotate(270, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
         	case Sprite.TRANS_ROT90:
         		_canvas.rotate(90, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
         	case Sprite.TRANS_ROT180:
         		_canvas.rotate(180, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
         	case Sprite.TRANS_ROT270:
         		_canvas.rotate(270, dx + newx + (width>>1), dy + newy + (height>>1));
        		break;
        	}
        }
        
        Rect srcRect = new Rect(x_src, y_src, x_src + width, y_src + height);
        Rect dstRect = new Rect(dx+ newx, dy + newy, dx + newx + width, dy + newy + height);
        _canvas.drawBitmap(src.bmp, srcRect, dstRect, null);
        
        //_canvas.drawBitmap(bitmap, matrix, paint);
        
        if(transform != Sprite.TRANS_NONE){
        	_canvas.restore();
        }
	}
	public void fillColor(int x, int y, int w, int h, int color){
		p.setColor(color);
		p.setStyle(Paint.Style.FILL);
		_canvas.drawRect(dx + x, dy + y, dx + x+w, dy + y+h, p);
	}
	public void setColor(int rgb){
		p.setColor(rgb | 0xFF000000);
	}
	public void setColor(int r, int g, int b) {
		int rgb = (r << 16) | (g << 8) | b;
		p.setColor(rgb | 0xFF000000);
	}
	public void drawRect(int x, int y, int w, int h){
		p.setStyle(Paint.Style.STROKE);
		_canvas.drawRect(dx + x, dy + y, dx + x+w, dy + y+h, p);
	}
	public void fillRect(int x, int y, int w, int h){
		p.setStyle(Paint.Style.FILL);
		_canvas.drawRect(dx + x, dy + y, dx + x+w, dy + y+h, p);
	}
	public void drawRoundRect(int x, int y, int w, int h, int rx, int ry){
		p.setStyle(Paint.Style.STROKE);
		_canvas.drawRoundRect(new RectF(dx + x, dy + y, dx + x + w, dy + y + h), rx, ry, p);
	}
	public void fillRoundRect(int x, int y, int w, int h, int rx, int ry){
		p.setStyle(Paint.Style.FILL);
		_canvas.drawRoundRect(new RectF(dx + x, dy + y, dx + x + w, dy + y + h), rx, ry, p);
	}
	
	public void translate(int x, int y){
		this.dx += x;
		this.dy += y;
	}
	public int getTranslateX(){
		return dx;
	}
	public int getTranslateY(){
		return dy;
	}
	protected void resetTranslate(){
		dx = dy = 0;
	}

	public int getClipX() {
		// TODO Auto-generated method stub
		////System.out.println("Graphics >> getClipX");
		return clip.left;
	}

	public int getClipY() {
		// TODO Auto-generated method stub
		////System.out.println("Graphics >> getClipX");
		return clip.top;
	}

	public int getClipWidth() {
		// TODO Auto-generated method stub
		////System.out.println("Graphics >> getClipX");
		return clip.width();
	}

	public int getClipHeight() {
		// TODO Auto-generated method stub
		////System.out.println("Graphics >> getClipX");
		return clip.height();
	}
}
